from flask import request
from flask_restx import Resource, Namespace, fields
from app.utils.auth import token_required
from app.utils.validators import validate_required_fields
from app.services.menu_service import MenuService
from . import admin_bp

# 创建菜单命名空间
menus_ns = Namespace('menus', description='菜单管理相关接口')

# 定义请求模型
menu_create_request = menus_ns.model('MenuCreateRequest', {
    'name': fields.String(required=True, description='菜单名称'),
    'path': fields.String(description='菜单路径'),
    'component': fields.String(description='组件路径'),
    'icon': fields.String(description='菜单图标'),
    'parent_id': fields.Integer(description='父菜单ID'),
    'sort': fields.Integer(description='排序'),
    'menu_type': fields.String(description='菜单类型'),
    'visible': fields.Boolean(description='是否可见'),
    'status': fields.Boolean(description='状态'),
    'perms': fields.String(description='权限标识'),
    'query': fields.String(description='路由参数'),
    'is_frame': fields.Boolean(description='是否外链'),
    'is_cache': fields.Boolean(description='是否缓存'),
})

menu_update_request = menus_ns.model('MenuUpdateRequest', {
    'name': fields.String(description='菜单名称'),
    'path': fields.String(description='菜单路径'),
    'component': fields.String(description='组件路径'),
    'icon': fields.String(description='菜单图标'),
    'parent_id': fields.Integer(description='父菜单ID'),
    'sort': fields.Integer(description='排序'),
    'menu_type': fields.String(description='菜单类型'),
    'visible': fields.Boolean(description='是否可见'),
    'status': fields.Boolean(description='状态'),
    'perms': fields.String(description='权限标识'),
    'query': fields.String(description='路由参数'),
    'is_frame': fields.Boolean(description='是否外链'),
    'is_cache': fields.Boolean(description='是否缓存'),
})

# Flask-RESTX兼容的响应函数
def success_response(data=None, message='操作成功', code=200):
    """成功响应格式 - Flask-RESTX兼容版本"""
    response = {
        'code': code,
        'message': message,
        'data': data
    }
    return response, code

def error_response(message='操作失败', code=400, data=None):
    """错误响应格式 - Flask-RESTX兼容版本"""
    response = {
        'code': code,
        'message': message,
        'data': data
    }
    return response, code

def paginate_response(query, page, per_page, total=None):
    """分页响应格式 - Flask-RESTX兼容版本"""
    if total is None:
        total = query.count()
    
    items = query.offset((page - 1) * per_page).limit(per_page).all()
    
    data = {
        'list': [item.to_dict() if hasattr(item, 'to_dict') else item for item in items],
        'pagination': {
            'page': page,
            'per_page': per_page,
            'total': total,
            'pages': (total + per_page - 1) // per_page
        }
    }
    
    return success_response(data)

@menus_ns.route('')
class MenuListAPI(Resource):
    """菜单列表"""
    
    @token_required
    def get(self, current_admin):
        # 检查是否需要树形结构
        tree = request.args.get('tree', type=bool)
        
        # 获取筛选参数
        keyword = request.args.get('keyword', '')
        visible = request.args.get('visible', type=int)
        status = request.args.get('status', type=int)
        
        if visible is not None:
            visible = bool(visible)
        if status is not None:
            status = bool(status)
        
        if tree:
            # 根据用户角色获取菜单
            if current_admin and current_admin.role_id:
                # 检查是否为超级管理员角色（通常role_id=1为超级管理员）
                if current_admin.role_id == 1:
                    # 超级管理员返回所有菜单（支持筛选）
                    data = MenuService.get_tree(keyword=keyword or None, visible=visible, status=status)
                else:
                    # 其他角色根据权限返回菜单
                    data = MenuService.get_tree_by_role(current_admin.role_id)
            else:
                # 没有角色信息时返回空
                data = []
            return success_response(data)
        
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 10, type=int)
        
        query, page, per_page = MenuService.get_list(page, per_page, keyword, visible, status)
        return paginate_response(query, page, per_page)
    
    @menus_ns.expect(menu_create_request)
    @token_required
    def post(self, current_admin):
        # 验证必填字段
        is_valid, error_msg = validate_required_fields(['name'])
        if not is_valid:
            return error_response(error_msg, 400)
        
        data = request.get_json()
        
        try:
            menu = MenuService.create(data)
            return success_response(menu.to_dict(), '创建成功')
        except Exception as e:
            return error_response(f'创建失败：{str(e)}', 500)


@menus_ns.route('/<int:menu_id>')
class MenuDetailAPI(Resource):
    """菜单详情"""
    
    @token_required
    def get(self, current_admin, menu_id):
        menu = MenuService.get_by_id(menu_id)
        if not menu:
            return error_response('菜单不存在', 404)
        
        return success_response(menu.to_dict())
    
    @menus_ns.expect(menu_update_request)
    @token_required
    def put(self, current_admin, menu_id):
        menu = MenuService.get_by_id(menu_id)
        if not menu:
            return error_response('菜单不存在', 404)
        
        data = request.get_json()
        
        try:
            updated_menu = MenuService.update(menu_id, data)
            return success_response(updated_menu.to_dict(), '更新成功')
        except Exception as e:
            return error_response(f'更新失败：{str(e)}', 500)
    
    @token_required
    def delete(self, current_admin, menu_id):
        result = MenuService.delete(menu_id)
        if isinstance(result, tuple):
            success, message = result
            if not success:
                return error_response(message, 400)
            return success_response(message=message)
        else:
            if not result:
                return error_response('删除失败，菜单不存在', 404)
            return success_response(message='删除成功')


@menus_ns.route('/options')
class MenuOptionsAPI(Resource):
    """菜单选项数据"""
    
    @token_required
    def get(self, current_admin):
        data = MenuService.get_parent_options()
        return success_response(data)


# 将命名空间注册到统一的API实例
from . import api
api.add_namespace(menus_ns, path='/menus') 